/*
    SUSAN® - Sole of Unix Save ANything

   Copyright (C) 2001-2011 Hechzh Property
   Copyright (C) 2016-2016 Skyatlas Co. CN

   
*/
/*
 * Kern Sibbald, May MMI previously in src/stored/fdmsg.c
 */
/**
 * @file
 * Subroutines to receive network data and handle
 * network signals for the FD and the SD.
 */

#include "include/susan.h" /* pull in global headers */
#include "lib/bnet.h"
#include "lib/bget_msg.h"
#include "lib/bsock.h"

static char OK_msg[] = "2000 OK\n";
static char TERM_msg[] = "2999 Terminate\n";

#define messagelevel 500

/**
 * This routine does a BnetRecv(), then if a signal was
 *   sent, it handles it.  The return codes are the same as
 *   bne_recv() except the BNET_SIGNAL messages that can
 *   be handled are done so without returning.
 *
 * Returns number of bytes read (may return zero)
 * Returns -1 on signal (BNET_SIGNAL)
 * Returns -2 on hard end of file (BNET_HARDEOF)
 * Returns -3 on error  (BNET_ERROR)
 */
int BgetMsg(SusanSocket* sock)
{
  int n;
  for (;;) {
    n = sock->recv();
    if (n >= 0) { /* normal return */
      return n;
    }
    if (IsBnetStop(sock)) { /* error return */
      return n;
    }

    /* BNET_SIGNAL (-1) return from BnetRecv() => network signal */
    switch (sock->message_length) {
      case BNET_EOD: /* end of data */
        Dmsg0(messagelevel, "Got BNET_EOD\n");
        return n;
      case BNET_EOD_POLL:
        Dmsg0(messagelevel, "Got BNET_EOD_POLL\n");
        if (sock->IsTerminated()) {
          sock->fsend(TERM_msg);
        } else {
          sock->fsend(OK_msg); /* send response */
        }
        return n; /* end of data */
      case BNET_TERMINATE:
        Dmsg0(messagelevel, "Got BNET_TERMINATE\n");
        sock->SetTerminated();
        return n;
      case BNET_POLL:
        Dmsg0(messagelevel, "Got BNET_POLL\n");
        if (sock->IsTerminated()) {
          sock->fsend(TERM_msg);
        } else {
          sock->fsend(OK_msg); /* send response */
        }
        break;
      case BNET_HEARTBEAT:
      case BNET_HB_RESPONSE:
        break;
      case BNET_STATUS:
        /* *****FIXME***** Implement BNET_STATUS */
        Dmsg0(messagelevel, "Got BNET_STATUS\n");
        sock->fsend(_("Status OK\n"));
        sock->signal(BNET_EOD);
        break;
      default:
        Emsg1(M_ERROR, 0, _("BgetMsg: unknown signal %d\n"),
              sock->message_length);
        break;
    }
  }
}
